home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 6: Level 6
/
17 Bit - Level 6 (1998)(Epic Marketing)[!].iso
/
quartz
/
q1082.dms
/
q1082.adf
/
src.lzh
/
Fig
/
SaveIFF.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-18
|
9KB
|
486 lines
#define MAKE_ID(a,b,c,d) (((LONG)(a) << 24) + ((LONG)(b) << 16) + ((LONG)(c) << 8) + (LONG)(d))
#define line_bytes(width) (((width + 15) >> 4) << 1)
#define FORM MAKE_ID('F','O','R','M')
#define ILBM MAKE_ID('I','L','B','M')
#define BMHD MAKE_ID('B','M','H','D')
#define CMAP MAKE_ID('C','M','A','P')
#define BODY MAKE_ID('B','O','D','Y')
#define CAMG MAKE_ID('C','A','M','G')
union bytes4
{
char b4_name[4];
LONG b4_type;
};
struct iff_chunk
{
union bytes4 iff_type;
LONG iff_length;
};
struct form_chunk
{
union bytes4 fc_type;
LONG fc_length;
union bytes4 fc_subtype;
};
struct BitMapHeader
{
UWORD w, h;
UWORD x, y;
UBYTE nPlanes;
UBYTE masking;
UBYTE compression;
UBYTE pad1;
UWORD transparentColor;
UBYTE xAspect, yAspect;
WORD pageWidth, pageHeight;
};
#define DUMP 0
#define RUN 1
#define MINRUN 3
#define MAXRUN 128
#define MAXDAT 128
/* pack_row - pass source line pointer, length of line, and file.
Returns # of bytes after compression. Returns 0 on write error.
Pass file = NULL to just find out length,
otherwise will write compressed row to file. */
LONG
pack_row(file,source,size)
FILE *file;
char *source;
LONG size;
{
char c,lastc = '\0';
LONG mode = DUMP;
LONG nbuf = 0; /* number of chars in buffer */
LONG rstart = 0; /* buffer index current run starts */
LONG putsize;
char buf[MAXDAT*3/2]; /* I think MAXDAT+1 would suffice */
putsize = 0;
buf[0] = lastc = *source++;/* so have valid lastc */
nbuf = 1;
size--; /* since one byte eaten. */
for(; size ; --size)
{
buf[nbuf++] = c = *source++;
switch(mode)
{
case DUMP: /* If the buffer is full, write the length byte, then the data */
if(nbuf > MAXDAT)
{
if(file != NULL)
{
if(fputc(nbuf-2,file) == EOF)
return(0);
if(fwrite(buf,nbuf-1,1,file) == EOF)
return(0);
}
putsize += nbuf;
buf[0] = c;
nbuf = 1;
rstart = 0;
break;
}
if(c == lastc)
{
if(nbuf - rstart >= MINRUN)
{
if(rstart > 0)
{
if(file != NULL)
{
if(fputc(rstart-1,file) == EOF)
return(0);
if(fwrite(buf,rstart,1,file) == EOF)
return(0);
}
putsize += rstart+1;
}
mode = RUN;
}
else
if(rstart == 0)
mode = RUN;
/* no dump in progress, so can't lose by making
these 2 a run. */
}
else
rstart = nbuf - 1;/* first of run */
break;
case RUN: if((c != lastc) ||(nbuf - rstart > MAXRUN))
{
/* output run */
if(file != NULL)
{
if(fputc(-(nbuf - rstart - 2),file) == EOF)
return(0);
if(fputc(lastc,file) == EOF)
return(0);
}
putsize += 2;
buf[0] = c;
nbuf = 1;
rstart = 0;
mode = DUMP;
}
break;
}
lastc = c;
}
switch(mode)
{
case DUMP: if(file != NULL)
{
if(fputc(nbuf-1,file) == EOF)
return(0);
if(fwrite(buf,nbuf,1,file) == EOF)
return(0);
}
putsize += nbuf+1;
break;
case RUN: if(file != NULL)
{
if(fputc(-(nbuf - rstart - 1),file) == EOF)
return(0);
if(fputc(lastc,file) == EOF)
return(0);
}
putsize += 2;
break;
}
return(putsize);
}
LONG
pack_bitmap(file,bm,height)
FILE *file;
struct BitMap *bm;
LONG height;
{
LONG i,j;
LONG row_length,compressed_length;
LONG plane_offset;
compressed_length = 0;
plane_offset = 0;
for(i = 0 ; i < height ; i++)
{
for(j = 0 ; j < bm -> Depth ; j++)
{
if((row_length = pack_row(file,bm -> Planes[j] + plane_offset,bm -> BytesPerRow)) == 0)
return(0);
compressed_length += row_length;
}
plane_offset += bm -> BytesPerRow;
}
if(compressed_length & 1) /*check to see odd length */
{
if(file != NULL) /*pad with 0 to make it even */
if(fputc(0,file) == EOF)
return(0);
compressed_length++;
}
return(compressed_length);
}
LONG
write_iff(name,colors,bits,xoff,yoff,width,height,compressed,pagewidth,pageheight,viewmodes)
char *name;
unsigned char *colors;
register struct BitMap *bits;
LONG xoff,yoff;
LONG width,height,compressed;
LONG pagewidth,pageheight;
LONG viewmodes;
{
FILE *file;
struct form_chunk chunk;
struct iff_chunk ichunk;
struct BitMapHeader header;
LONG bits_size,numcols = 32,row_offset;
register LONG i,j;
if(bits)
{
if((numcols = 1 << bits -> Depth) == 64)
numcols = 32;
if(viewmodes & HAM)
numcols = 16;
}
if(!(file = fopen(name,"w")))
return(FALSE);
/* say its a FORM ILBM */
chunk . fc_type . b4_type = FORM;
chunk . fc_subtype . b4_type = ILBM;
chunk . fc_length = sizeof(struct form_chunk) + 3 * sizeof(struct iff_chunk) + numcols * 3 + sizeof(struct BitMapHeader) + sizeof(LONG);
if(bits)
{
if(compressed)
{
if((bits_size = pack_bitmap(NULL,bits,height)) == 0)
{
fclose(file);
return(FALSE);
}
}
else
bits_size = bits -> BytesPerRow * bits -> Rows * bits -> Depth;
chunk . fc_length += bits_size;
}
else
chunk . fc_length -= sizeof(struct iff_chunk);
if(fwrite(&chunk,sizeof(chunk),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
/* here comes a BitMapHeader */
ichunk . iff_type . b4_type = BMHD;
ichunk . iff_length = sizeof(header);
if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
/* initialize the BitMapHeader to normal values */
header . masking = 0;
header . pad1 = 0;
header . transparentColor = 0;
if(compressed)
header . compression = 1;
else
header . compression = 0;
header . pageWidth = pagewidth;
header . pageHeight = pageheight;
header . yAspect = 11;
viewmodes &= ~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO);
if((viewmodes & HIRES) && (viewmodes & LACE))
header . xAspect = 10;
if(!(viewmodes & HIRES) && (viewmodes & LACE))
header . xAspect = 20;
if((viewmodes & HIRES) && !(viewmodes & LACE))
header . xAspect = 5;
if(!(viewmodes & HIRES) && !(viewmodes & LACE))
header . xAspect = 10;
/* if it's not just a color map give the dimensions of rasters */
if(bits)
{
header . w = width;
header . h = height;
header . nPlanes= bits -> Depth;
header . x = xoff;
header . y = yoff;
}
if(fwrite(&header,sizeof(header),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
/* squirt out the color map */
ichunk . iff_type . b4_type = CMAP;
ichunk . iff_length = numcols * 3;
if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
if(fwrite(colors,3 * numcols,1,file) == EOF)
{
fclose(file);
return(FALSE);
}
/* send it a CAMG chunk */
ichunk . iff_type . b4_type = CAMG;
ichunk . iff_length = sizeof(LONG);
if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
if(fwrite(&viewmodes,sizeof(LONG),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
/* if they be bits then squirt out the bits */
if(bits)
{
ichunk . iff_type . b4_type = BODY;
ichunk . iff_length = bits_size;
if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
{
fclose(file);
return(FALSE);
}
if(compressed)
{
if(pack_bitmap(file,bits,height) == 0)
{
fclose(file);
return(FALSE);
}
}
else
{
i = height;
row_offset = 0;
while(--i >= 0)
{
for(j = 0 ; j < bits -> Depth ; j++)
{
if(fwrite(bits -> Planes[j] + row_offset,height,1,file) == EOF)
{
fclose(file);
return(FALSE);
}
row_offset += bits -> BytesPerRow;
}
}
}
}
fclose(file);
return(TRUE);
}
LONG
SaveRPort(RPort,VPort,LeftEdge,TopEdge,Width,Height,ParentWidth,ParentHeight,Cookie,Name)
struct RastPort *RPort;
struct ViewPort *VPort;
LONG LeftEdge,TopEdge,Width,Height,ParentWidth,ParentHeight,Cookie;
STRPTR Name;
{
char ColTable[32 * 3];
struct BitMap DstMap,*SMap = RPort -> BitMap;
LONG IFF_Result;
LONG i,Modes;
LONG r,g,b;
extern struct GfxBase *GfxBase;
if(!RPort || !VPort || !Name || Width < 1 || Height < 1)
return(FALSE);
if(LeftEdge || TopEdge || Cookie)
{
Cookie = TRUE;
InitBitMap(&DstMap,SMap -> Depth,Width,Height);
for(i = 0 ; i < SMap -> Depth ; i++)
{
if(!(DstMap . Planes[i] = (PLANEPTR)AllocMem(line_bytes(Width) * Height,MEMF_CHIP | MEMF_CLEAR)))
{
IFF_Result = FALSE;
goto Stop;
}
}
BltBitMap(SMap,LeftEdge,TopEdge,&DstMap,0,0,Width,Height,0xC0,0xFF);
SMap = &DstMap;
}
if(GfxBase -> LibNode . lib_Version >= 36)
Modes = GetVPModeID(VPort);
else
Modes = VPort -> Modes;
for(i = 0 ; i < 32 ; i++)
{
UWORD TmpCol = GetRGB4(VPort -> ColorMap,i);
r = (TmpCol >> 8) & 0xF;
g = (TmpCol >> 4) & 0xF;
b = (TmpCol ) & 0xF;
ColTable[i * 3 + 0] = r << 4;
ColTable[i * 3 + 1] = g << 4;
ColTable[i * 3 + 2] = b << 4;
}
IFF_Result = write_iff(Name,ColTable,SMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,Modes);
Stop: if(Cookie)
for(i = 0 ; i < DstMap . Depth ; i++)
if(DstMap . Planes[i])
FreeMem(DstMap . Planes[i],line_bytes(Width) * Height);
return(IFF_Result);
}